package anna;

import java.util.ArrayList;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.*;

public class MyThreadFinal extends Thread {

	private CountDownLatch cdl = null;
	private ArrayList<CountDownLatch> dependentCdl = null;

	public MyThreadFinal(CountDownLatch cdl, ArrayList<CountDownLatch> dependentCdl) {
		this.cdl = cdl;
		this.dependentCdl = dependentCdl;
	}

	private void criticalZone() {
		try {
			if (this.cdl != null) {
				this.cdl.await();
			}

			System.out.println(Thread.currentThread().getName());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(this.dependentCdl != null){
				for (CountDownLatch countDownLatch : this.dependentCdl) {
					countDownLatch.countDown();
				}
			}

		}
	}

	@Override
	public void run() {
		criticalZone();
	}

	public static void main(String[] sa) {
		
		ArrayList <CountDownLatch> arrS1 = new ArrayList();
		ArrayList <CountDownLatch> arrS2 = new ArrayList();
		ArrayList <CountDownLatch> arrS3 = new ArrayList();
		ArrayList <CountDownLatch> arrS4 = new ArrayList();
		ArrayList <CountDownLatch> arrS5 = new ArrayList();
		
		CountDownLatch cdl2 = new CountDownLatch(1);
		CountDownLatch cdl3 = new CountDownLatch(1);
		CountDownLatch cdl4 = new CountDownLatch(1);
		CountDownLatch cdl5 = new CountDownLatch(2);
		CountDownLatch cdl6 = new CountDownLatch(2);
		CountDownLatch cdl7 = new CountDownLatch(2);
		
		arrS1.add(cdl2);
		arrS1.add(cdl3);
		arrS1.add(cdl4);
		
		arrS1.add(cdl5);
		arrS1.add(cdl6);
		arrS1.add(cdl7);
		
		arrS2.add(cdl5);
		arrS3.add(cdl6);
		arrS4.add(cdl7);
		
		MyThreadFinal m1 = new MyThreadFinal(null, arrS1);
		m1.setName("thread 1");
		MyThreadFinal m2 = new MyThreadFinal(cdl2, arrS2);
		m2.setName("thread 2");
		MyThreadFinal m3 = new MyThreadFinal(cdl3, arrS3);
		m3.setName("thread 3");
		MyThreadFinal m4 = new MyThreadFinal(cdl4, arrS4);
		m4.setName("thread 4");
		MyThreadFinal m5 = new MyThreadFinal(cdl5, null);
		m5.setName("thread 5");
		MyThreadFinal m6 = new MyThreadFinal(cdl6, null);
		m6.setName("thread 6 ");
		MyThreadFinal m7 = new MyThreadFinal(cdl7, null);
		m7.setName("thread 7");

		m7.start();
		m6.start();
		m5.start();
		m4.start();
		m3.start();
		m2.start();
		m1.start();
	}
}
